from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QVBoxLayout, QWidget
from PyQt5.QtCore import QPropertyAnimation, QRect, Qt, pyqtProperty
from PyQt5.QtGui import QColor, QPainter, QPen


class ScannerAnimation(QLabel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._scan_pos = 0  # 使用带下划线的私有变量
        self.scan_color = QColor(0, 255, 0, 128)  # 半透明绿色扫描线
        self.setMinimumSize(400, 400)
        self.setText("模拟扫描区域\n\n这里是扫描的内容")
        self.setAlignment(Qt.AlignCenter)
        self.setStyleSheet("background-color: #333; color: white; font-size: 16px;")

    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QPainter(self)
        pen = QPen(self.scan_color, 3)
        painter.setPen(pen)

        # 绘制扫描线
        painter.drawLine(0, self._scan_pos, self.width(), self._scan_pos)

        # 绘制扫描头效果
        brush = QPen(QColor(0, 255, 0, 200), 8)
        painter.setPen(brush)
        painter.drawPoint(self.width() // 2, self._scan_pos)

    # 使用pyqtProperty定义可动画属性
    @pyqtProperty(int)
    def scan_pos(self):
        return self._scan_pos

    @scan_pos.setter
    def scan_pos(self, pos):
        self._scan_pos = pos
        self.update()  # 触发重绘


class ScannerWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("扫描动画演示")

        self.scanner = ScannerAnimation()

        layout = QVBoxLayout()
        layout.addWidget(self.scanner)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        # 创建动画
        self.animation = QPropertyAnimation(self.scanner, b"scan_pos")  # 使用bytes字符串
        self.animation.setDuration(2000)  # 2秒完成一次扫描
        self.animation.setStartValue(0)
        self.animation.setEndValue(self.scanner.height())
        self.animation.setLoopCount(-1)  # 无限循环
        self.animation.start()

        self.resize(500, 500)


if __name__ == "__main__":
    app = QApplication([])
    window = ScannerWindow()
    window.show()
    app.exec_()